#include <stdio.h>
#include "image.h"
#include <math.h>

typedef float vec3[3];

typedef struct _ray {
    vec3 o, d;
}ray;

typedef struct _sphere {
    vec3 c;
    float radius;
} sphere;

typedef struct _camera {
    vec3 pos, viewdir, up, rightvec;
    vec3 lookatpt;
    //frustum
    float left, right, top, bottom, near, far;
}camera;

void initCamera(camera *c, float posx, float posy, float posz, float viewx, float viewy, float viewz, float upx, float upy, float upz, float rightx, float righty, float rightz) {
    c->pos[0] = posx;
    c->pos[1] = posy;
    c->pos[2] = posz;

    c->viewdir[0] = viewx;
    c->viewdir[1] = viewy;
    c->viewdir[2] = viewz;

    c->up[0] = upx;
    c->up[1] = upy;
    c->up[2] = upz;

    c->rightvec[0] = rightx;
    c->rightvec[1] = righty;
    c->rightvec[2] = rightz;
}

int intersectSphere(sphere s, ray r) {
    vec3 dst;
    dst[0] = r.o[0] - s.c[0];
    dst[1] = r.o[1] - s.c[1];
    dst[2] = r.o[2] - s.c[2];

    float b = dst[0]*r.d[0] + dst[1]*r.d[1] + dst[2]*r.d[2];
    float c = dst[0]*dst[0] + dst[1]*dst[1] + dst[2]*dst[2] - s.radius*s.radius;
    float d = b*b - c;

    if(d > 0)
        return 1;
    return 0;
}

int main() {
    int imgw = 50, imgh = 50;
    //criar imagem final
    unsigned char img[50][50][3];

    camera c;
    initCamera(&c, 0.0, 0.0, 10.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0);
    
    //coloca camera apontada pra a origem
    c.lookatpt[0] = 0.0;
    c.lookatpt[1] = 0.0;
    c.lookatpt[2] = 0.0;

    //distancia da camera ate o ponto onde ela esta focada
    float dist = sqrt((c.pos[0] - c.lookatpt[0])*(c.pos[0] - c.lookatpt[0]) +
                      (c.pos[1] - c.lookatpt[1])*(c.pos[1] - c.lookatpt[1]) +
                      (c.pos[2] - c.lookatpt[2])*(c.pos[2] - c.lookatpt[2]));

    //near plane do frustum fica sendo esse quadrado de lado 2*dist
    c.left = -dist;
    c.right = dist;
    c.bottom = -dist;
    c.top = dist;
    //precisa ver como usar esse near e far. talvez a única utilidade seja limitar o começo e o fim do raio.
    c.near = 0.0;
    c.far = 2*dist;

    sphere s;
    s.c[0] = 0.0;
    s.c[1] = 0.0;
    s.c[2] = 0.0;
    s.radius = 3;

    for(int i = 0; i < imgw; i++) {
        for(int j = 0; j < imgh; j++) {
            //cria raio saindo da camera
            ray r;
            r.o[0] = c.pos[0];
            r.o[1] = c.pos[1];
            r.o[2] = c.pos[2];

            //mapeia as coordenadas de janela pra coordenadas de mundo
            //o centro do mundo sera no centro da tela, por isso a subtração e a divisão
            float xw = (c.right - c.left)*(i - imgw/2.0)/imgw;
            float yw = (c.top - c.bottom)*(j - imgh/2.0)/imgh;
            vec3 p;
            p[0] = c.lookatpt[0]*dist + xw*c.rightvec[0] + yw*c.up[0];
            p[1] = c.lookatpt[1]*dist + xw*c.rightvec[1] + yw*c.up[1];
            p[2] = c.lookatpt[2]*dist + xw*c.rightvec[2] + yw*c.up[2];

            r.d[0] = p[0] - c.pos[0];
            r.d[1] = p[1] - c.pos[1];
            r.d[2] = p[2] - c.pos[2];
            //normalizar direcao
            float dirlength = sqrt(r.d[0]*r.d[0] + r.d[1]*r.d[1] + r.d[2]*r.d[2]);
            r.d[0] /= dirlength;
            r.d[1] /= dirlength;
            r.d[2] /= dirlength;
            
            if(intersectSphere(s, r)) {
                img[i][j][0] = 254.0;
                img[i][j][1] = 0.0;
                img[i][j][2] = 0.0;
                printf("intersecao\n");
            } else {
                img[i][j][0] = 0.0;
                img[i][j][1] = 0.0;
                img[i][j][2] = 0.0;
            }

        }
    }

    stbi_write_tga("rayfail.tga", imgw, imgh, 3, img );
    return 0;
}
